﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MoneyWentWhere.WinFormsUI.Reports
{
    interface IReportRow
    {
        int NodeCount { get; }
        IEnumerable NodeObjects { get; }
    }

    abstract class ReportRow<T> : IReportRow
        where T : class
    {
        // Normally row has either an item or subnodes
        T _item = null;
        List<ReportRow<T>> _nodes;

        public T Item 
        { 
            get { return _item; }
            private set
            {
                _item = value;
                CalculateCells(Item);
            }
        }

        public List<ReportRow<T>> Nodes
        {
            get
            {
                if (_nodes == null) { _nodes = new List<ReportRow<T>>(); }
                return _nodes;
            }
        }

        public int NodeCount { get { return _nodes == null ? 0 : _nodes.Count; } }
        public IEnumerable NodeObjects { get { return _nodes; } }

        public void AddNode(T item)
        {
            ReportRow<T> row = CreateChildNode();
            row.Item = item;
            Nodes.Add(row);
        }

        protected virtual ReportRow<T> CreateChildNode()
        {
            return (ReportRow<T>)Activator.CreateInstance(this.GetType());
        }

        public void AddNode(ReportRow<T> row)
        {
            Nodes.Add(row);
        }

        public void AddAllNodesAndCalculate(IEnumerable<T> items)
        {
            foreach (T item in items) { AddNode(item); }
            CalculateCells(Nodes);
        }

        public void AddAllNodesAndCalculate(IEnumerable<ReportRow<T>> rows)
        {
            foreach (ReportRow<T> row in rows) { AddNode(row); }
            CalculateCells(Nodes);
        }

        protected virtual void CalculateCells(T item) { }
        protected virtual void CalculateCells(List<ReportRow<T>> nodes) { }

        public void CalculateCells()
        {
            if (IsLeaf) { CalculateCells(Item); }
            else { CalculateCells(Nodes); }
        }

        public bool IsLeaf
        {
            get { return _nodes == null || _nodes.Count == 0; }
        }

    }
}
